/*
This module is part of the SoftIWS system
Copyright (c)SCC, Inc.  2010
All Rights Reserved

This document contains unpublished, confidential and proprietary
information of SCC, Inc. No disclosure or use of
any portion of the contents of these materials may be made without the
express written consent of Soft Computer Consultants, Inc.

Author:    Daniel Dus <ddus@softsystem.pl>

Created:   03 Sep 2012
 */
package org.javacc.parser;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author Daniel Dus <ddus@softsystem.pl>
 */
public class OtherFilesGenCS  extends JavaCCGlobals implements JavaCCParserConstants {
    static public void start() throws MetaParseException {

    Token t = null;
    if (JavaCCErrors.get_error_count() != 0) throw new MetaParseException();

    //CSFiles.gen_JavaCCDefs();
    
    
    if (Options.getUserTokenManager()) {
      CSFiles.gen_TokenManager();
    } else if (Options.getUserCharStream()) {
      CSFiles.gen_CharStream();
    } else {
      if (Options.getJavaUnicodeEscape()) {
        CSFiles.gen_CSCharStream();
      } else {
        CSFiles.gen_SimpleCharStream();
      }
    }
    
    //CSFiles.gen_SimpleCharStream();
    CSFiles.gen_Token();
    CSFiles.gen_TokenMgrError();
    CSFiles.gen_ParseException();
    CSFiles.gen_ErrorHandler();

    try {
      ostr = new java.io.PrintWriter(
                new java.io.BufferedWriter(
                   new java.io.FileWriter(
                     new java.io.File(Options.getOutputDirectory(), cu_name + "Constants.cs")
                   ),
                   8192
                )
             );
    } catch (java.io.IOException e) {
      JavaCCErrors.semantic_error("Could not open file " + cu_name + "Constants.cs for writing.");
      throw new Error();
    }

    List tn = new ArrayList(toolNames);
    tn.add(toolName);
    ostr.println("/* " + getIdString(tn, cu_name + "Constants.cs") + " */");

    if (cu_to_insertion_point_1.size() != 0 &&
        ((Token)cu_to_insertion_point_1.get(0)).kind == PACKAGE
       ) {
      for (int i = 1; i < cu_to_insertion_point_1.size(); i++) {
        if (((Token)cu_to_insertion_point_1.get(i)).kind == SEMICOLON) {
          printTokenSetup((Token)(cu_to_insertion_point_1.get(0)));
          for (int j = 0; j <= i; j++) {
            t = (Token)(cu_to_insertion_point_1.get(j));
            printToken(t, ostr);
          }
          printTrailingComments(t, ostr);
          ostr.println("");
          ostr.println("");
          break;
        }
      }
    }
    ostr.println("");
    ostr.println("/**");
    ostr.println(" * Token literal values and constants.");
    ostr.println(" * Generated by org.javacc.parser.OtherFilesGen#start()");
    ostr.println(" */");

    ostr.println("using System;");
    ostr.println("");
    if (Options.stringValue("NAMESPACE").length() > 0) {
      ostr.println("namespace " + Options.stringValue("NAMESPACE") + " {");
    }

    RegularExpression re;
    String constPrefix = "  public const";
    ostr.println("  public class " + cu_name + "Constants ");
    
    if (cu_to_insertion_point_2.size() != 0) 
    {
      boolean implementsExists = false;
        if (((Token)cu_to_insertion_point_2.get(0)).specialToken != null)
        {
          implementsExists = true;
        }
       
        if (implementsExists)
        {
         ostr.print(getSpecialStringToPrint((Token)(cu_to_insertion_point_2.get(0))));
         
        }
        ostr.print("{");
    }
    
    ostr.println("  /** End of File. */");
    ostr.println(constPrefix + "  int _EOF = 0;");
    ostr.println("  /** RegularExpression Id. */");
    for (java.util.Iterator it = ordered_named_tokens.iterator(); it.hasNext();) {
      re = (RegularExpression)it.next();
      ostr.println(constPrefix + " int " + re.label + " = " + re.ordinal + ";");
    }
    ostr.println("");

    if (!Options.getUserTokenManager() && Options.getBuildTokenManager()) {
      ostr.println("  /** Lexical state. */");
      for (int i = 0; i < Main.lg.lexStateName.length; i++) {
        ostr.println(constPrefix + " int " + LexGen.lexStateName[i] + " = " + i + ";");
      }
      ostr.println("");
    }

    ostr.println("  /** Literal token values. */");
    ostr.println("  public static String[] tokenImage = {");
    ostr.println("    \"<EOF>\",");

    for (java.util.Iterator it = rexprlist.iterator(); it.hasNext();) {
      TokenProduction tp = (TokenProduction)(it.next());
      List respecs = tp.respecs;
      for (java.util.Iterator it2 = respecs.iterator(); it2.hasNext();) {
        RegExprSpec res = (RegExprSpec)(it2.next());
        re = res.rexp;
        ostr.print("    ");
        if (re instanceof RStringLiteral) {
          ostr.println("\"\\\"" + add_escapes(add_escapes(((RStringLiteral)re).image)) + "\\\"\",");
        } else if (!re.label.equals("")) {
          ostr.println("\"<" + re.label + ">\",");
        } else {
          if (re.tpContext.kind == TokenProduction.TOKEN) {
            JavaCCErrors.warning(re, "Consider giving this non-string token a label for better error reporting.");
          }
          ostr.println("\"<token of kind " + re.ordinal + ">\",");
        }

      }
    }

    ostr.println("   };");
    ostr.println("  }");
    if (Options.stringValue("NAMESPACE").length() > 0) {
      ostr.println("}");
    }

    ostr.close();

  }

   // Used by the CPP code generatror
   public static void printCharArray(java.io.PrintWriter ostr, String s) {
     ostr.print("{");
     for (int i = 0; i < s.length(); i++) {
       ostr.print("0x" + Integer.toHexString((int)s.charAt(i)) + ", ");
     }
     ostr.print("0}");
   }

  static private java.io.PrintWriter ostr;

  public static void reInit()
  {
    ostr = null;
  }

  protected static String getSpecialStringToPrint(Token t) {
    String retval = "";
    Token tt = t.specialToken;
    if (tt != null) {
      tt = updateSpecialToken(tt);
      while (tt != null) {
        retval += getStringForTokenOnly(tt);
        tt = tt.next;
      }
    }

    return retval;
  }

  protected static Token updateSpecialToken(Token tt)
  {
     if (tt.kind == JavaCCParserConstants.SPECIAL_CS_CODE)
      {
        tt.image = tt.image.substring(5);
        tt.image = tt.image.substring(0, tt.image.length() -2);
        tt.kind = JavaCCParserConstants.MULTI_LINE_COMMENT;
      }
      
      if (tt.kind == JavaCCParserConstants.SPECIAL_JAVA_CODE)
      {
        tt.image = "";
        tt.kind = JavaCCParserConstants.MULTI_LINE_COMMENT;
      }
    
    while (tt.specialToken != null)
    {
      if (tt.specialToken.kind == JavaCCParserConstants.SPECIAL_CS_CODE )
      {
        tt.specialToken.image = tt.specialToken.image.substring(5);
        tt.specialToken.image = tt.specialToken.image.substring(0, tt.specialToken.image.length() -2);
        tt.specialToken.kind = JavaCCParserConstants.MULTI_LINE_COMMENT;
      } else if (tt.specialToken.kind == JavaCCParserConstants.SPECIAL_JAVA_CODE)
      {
        tt.specialToken.image = tt.specialToken.image.substring(7);
        tt.specialToken.image = tt.specialToken.image.substring(0, tt.specialToken.image.length() -2);
        tt.specialToken.kind = JavaCCParserConstants.MULTI_LINE_COMMENT;
      }
      
      if (tt.specialToken.kind == JavaCCParserConstants.SPECIAL_CS_CODE || tt.specialToken.kind == JavaCCParserConstants.SPECIAL_JAVA_CODE)
      {
        tt.specialToken.image = "";
        tt.specialToken.kind = JavaCCParserConstants.MULTI_LINE_COMMENT;
      }
      tt = tt.specialToken;
    }
    return tt;
  }
  
  protected static String getStringForTokenOnly(Token t) {
    String retval = "";
    for (; cline < t.beginLine; cline++) {
      retval += "\n"; ccol = 1;
    }
    for (; ccol < t.beginColumn; ccol++) {
      retval += " ";
    }
    if (t.kind == JavaCCParserConstants.STRING_LITERAL ||
        t.kind == JavaCCParserConstants.CHARACTER_LITERAL)
       retval += addUnicodeEscapes(t.image);
    else
       retval += t.image;
    cline = t.endLine;
    ccol = t.endColumn+1;
    if (t.image.length() > 0) {
      char last = t.image.charAt(t.image.length()-1);
      if (last == '\n' || last == '\r') {
        cline++; ccol = 1;
      }
    } 

    return retval;
  }
}
